package ngat.oss;

import ngat.message.OSS.*;
import ngat.util.logging.*;
import ngat.phase2.*; 
import ngat.instrument.*;
import ngat.phase2.nonpersist.*;

import java.util.*;
import java.io.*;

import jyd.dbms.*;
import jyd.storable.*;
import jyd.collection.*;

/**
 * Action: Sent by USR to RE-retreive Proposal for editing. The Proposal is locked for
 * exclusive use by this user until they submit changes. No scheduling can take place
 * on any Groups in this Proposal until it is unlocked again. 
 * @author S.N.Fraser
 * $Id: RELOAD_PROPOSALImpl.java,v 1.1 2006/11/27 08:45:00 snf Exp $
 */
public class RELOAD_PROPOSALImpl extends TransactionImpl {
    
    /** The path used to identify the Proposal in the OSS database. */
    protected Path proposalPath;
    
    /** The path used to identify the current User (editor) in the database. */
    protected Path editorPath;

    /** The key to be used to lock the Proposal in the Database. */
    protected int key;

    /** Create a RELOAD_PROPOSALImpl for the supplied request.*/
    public RELOAD_PROPOSALImpl(RELOAD_PROPOSAL request) {
	super(request);
	this.proposalPath = request.getProposalPath();
	this.editorPath   = request.getEditorPath();
	this.key          = request.getKey();
    }

    /**
     * RE-Retrieves the Proposal specified
     * @return Proposal or an OSS_Error.
     */
    public TRANSACTION_DONE exec() { 

	Proposal proposal = null;	

	Transaction t = null;
	try {
	    t = Transaction.current();
	    
	    // Fetch the Proposal.
	    proposal = null;
	    try {
		proposal = OSS_Utilities.fetchProposal(proposalPath);
	    } catch (IOException iox) {
		logger.log(1, CLASS, id, "exec",
			   "Proposal: "+proposalPath.toString()+
			   " Error fetching from Database: "+iox);
		return error(TRANSACTION.DATABASE_READ_ERROR,			   
				     "Proposal: "+proposalPath.toString()+
				     " Error reading from database: "+iox);
	    }		
	 
	    // Check it exists.
	    if (proposal == null) {		
		logger.log(1, CLASS, id, "exec", 
			   "Proposal: "+proposalPath.toString()+" Not in database.");
		return error(TRANSACTION.PATH_RESOLUTION_ERROR, 
				     "Could not find Proposal: "+proposalPath.toString());
	    } 

	    logger.log(1, CLASS, id, "exec", 
		       "Prop: "+proposal.getName()+" lock: "+proposal.getLock());
			    
	    if (proposal.isLocked()) {	   
		// Someone has already locked this one for editing.
		// See if it has been exported.
		if (proposal.isExported()) {
		    //##GET-1
		    logger.log(1, CLASS, id, "exec", 
			       "Proposal "+proposal.getName()+" is exported can reload?");
		    // Someone has Exported it, so we can upload.
		    // Let other Users know who is editing now.
		    proposal.setLastEditor(editorPath.toString()); 
		    proposal.setLastLocked(System.currentTimeMillis());
		    proposal.setExported(false); // Dont let anyone else upload !		   
		    proposal.lock(key); 
		} else {
		    // See if we have it ourselves antway.
		    if (proposal.getLastEditor().equals(editorPath.toString())) {
			//##GET-2
			logger.log(1, CLASS, id, "exec", 
				   "Proposal "+proposal.getName()+
				   " current editor: "+editorPath.toString()+" can reload");
			proposal.setLastEditor(editorPath.toString()); 
			proposal.setLastLocked(System.currentTimeMillis());
			proposal.setExported(false); // Dont let anyone else upload !			
			proposal.lock(key); 
		    } else {
			//##ERROR-2
			// We dont have it but someone does!
			logger.log(1, CLASS, id, "exec", 
				   "Attempt to access locked Proposal: "+
				   proposalPath.toString()+" lock is: "+proposal.getLock());
			Date date = new Date(proposal.getLastUnLocked());
			return error(TRANSACTION.ILLEGAL_DATABASE_ACCESS,
					     " The Proposal you are trying to access was locked by user: "
					     +proposal.getLastEditor()+ " at time: "+date.toGMTString());
		    }
		}
	    } else {
		// Its not locked anyway  but we cant lock it due to a lower lock!
		if (!proposal.canLock()) {		
		    //##ERROR-3	
		    // One or more Groups/Observations are currently being scheduled/updated
		    // by the RCS or some other client. User will have to wait..
		    logger.log(1, CLASS, id, "exec", 
			       "Proposal "+proposal.getName()+
			       " subtree is locked out at lower level.");
		    
		    return error(RELOAD_PROPOSAL.LOW_LEVEL_LOCKOUT, 
				 "A lock is held by another client on a subset of this Proposal: "+
				 proposalPath.toString());
		} else {	
		    //##GET-3
		    // The Proposal is unlocked and is lockable by us.
		    // Let other Users know who is editing now.
		    proposal.setLastEditor(editorPath.toString()); 
		    proposal.setLastLocked(System.currentTimeMillis());
		    proposal.lock(key); 
		}	    
	    }	    
	} finally {
	    t.commit();
	}
	
	try {
	    OSS_Utilities.storeProposal(proposal);
	} catch (IOException ix) {
	    logger.log(1, CLASS, id, "exec",
		       "Proposal ["+proposal.getFullPath()+
		       "] Unable to Store: "+ix);
	    return error(TRANSACTION.DATABASE_UPDATE_ERROR, 
				 "Proposal ["+proposal.getFullPath()+
				 "] Unable to Store: "+ix);
	}

	// Note: Unlock to free subtree then relock at Proposal level.
	proposal.forceUnLock();	
	proposal.setLock(key);	

	RELOAD_PROPOSAL_DONE done = new RELOAD_PROPOSAL_DONE(id);
	done.setProposal(proposal);
	done.setSuccessful(true);
	return done;
	
    }
    
} // Class Def. [USR-GetProposal_Req].

/** $Log: RELOAD_PROPOSALImpl.java,v $
/** Revision 1.1  2006/11/27 08:45:00  snf
/** Initial revision
/**
/** Revision 1.1  2001/02/23 18:51:14  snf
/** Initial revision
/** */
